package com.demo.testversion1

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.forEach
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import org.junit.Test

/**
 * Created by zhangyuncai on 2025/1/21.
 * 描述：
 */
class CoroutineTest06 {
    fun simpleList(): List<Int> = listOf<Int>(1, 2, 3)

    fun simpleSequence():Sequence<Int> = sequence {
        for(index in 1 .. 3)
        {
            Thread.sleep(1000L)
            yield(index)
        }
    }

   suspend fun simpleList2(): List<Int> {
       delay(1000L)
      return listOf<Int>(1, 2, 3)
   }

    @Test
    fun `test multiple values`() {
//        simpleList().forEach { value ->
//            println("value:$value")
//        }
//        simpleSequence().forEach { value ->
//            println("value:$value")
//        }
    }

    /*suspend*/ fun simpleFlow() = flow<Int> {//flow可以不需要suspend
        for (index in 0 .. 3)
        {
            delay(1000L)
            emit(index)//发射一个元素
        }
    }

    @Test
    fun `test multiple values2`():Unit= runBlocking {
        simpleList2().forEach { value->
            println("value:$value")
        }
    }

    @Test
    fun `test multiple values3`():Unit= runBlocking {
        simpleFlow().collect { value->
            println("value:$value")
        }
    }

    fun simpleFlow2() = flow<Int> {//flow可以不需要suspend
        println("started")
        for (index in 1 .. 3)
        {
            delay(1000L)
            emit(index)//发射一个元素
        }
    }

    @Test
    fun `test flow is cold`():Unit= runBlocking {
        val flow=simpleFlow2()
        println("collect")
        flow.collect{value->
            println("value:$value")
        }
        println("collect again")
        flow.collect{value->
            println("value:$value")
        }
    }

    @Test
    fun `test flow continuation`():Unit= runBlocking {
        (1 .. 5).asFlow().filter {
            it%2==0
        }.map {
            "string $it"
        }.collect{
            println("collect ${it}")
        }
    }

    @Test
    fun `test flow builder`():Unit= runBlocking {
        flowOf("one","two","three")
            .onEach { delay(1000) }
            .collect{
                println("collect ${it}")
            }
        (1..3).asFlow().collect{
            println("collect ${it}")
        }
    }

    fun simpleFlow3() = flow<Int> {//flow可以不需要suspend
        println("started:${Thread.currentThread().name}")
        for (index in 1 .. 3)
        {
            delay(1000L)
            emit(index)//发射一个元素
        }
    }
    fun simpleFlow4() = flow<Int> {//flow可以不需要suspend
        withContext(Dispatchers.IO){//不能这样改变上下文
            println("started:${Thread.currentThread().name}")
            for (index in 1 .. 3)
            {
                delay(1000L)
                emit(index)//发射一个元素
            }
        }

    }
    fun simpleFlow5() = flow<Int> {//flow可以不需要suspend
        println("started:${Thread.currentThread().name}")
        for (index in 1 .. 3)
        {
            delay(1000L)
            emit(index)//发射一个元素
        }

    }.flowOn(Dispatchers.Default)

    @Test
    fun `test flow context`():Unit= runBlocking {
        simpleFlow3().collect{
            println("collect ${it},${Thread.currentThread().name}")
        }
    }

    @Test
    fun `test flow context2`():Unit= runBlocking {
        simpleFlow4().collect{
            println("collect ${it},${Thread.currentThread().name}")
        }
    }
    @Test
    fun `test flow context3`():Unit= runBlocking {
        simpleFlow5().collect{
            println("collect ${it},${Thread.currentThread().name}")
        }
    }
    @Test
    fun `test flow context4`():Unit= runBlocking {
        (1..3)
            .asFlow()
            .onEach { delay(1000) }
            .flowOn(Dispatchers.Default)
            .onEach {
                event->
                println("event:${event} ${Thread.currentThread().name}")
            }
            .collect{
                println("collect ${it},${Thread.currentThread().name}")
            }
    }
    @Test
    fun `test flow context5`():Unit= runBlocking {
        (1..3)
            .asFlow()
            .onEach { delay(1000) }
            .flowOn(Dispatchers.Default)
            .onEach {
                    event->
                println("event:${event} ${Thread.currentThread().name}")
            }
            .launchIn(CoroutineScope(Dispatchers.IO))
            .join()
    }
}